﻿using BusinessLayer;
using EntitiesLayer;
using QuidditchWpf.ViewModel;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;


namespace QuidditchWpf.ViewModel
{
    /// <summary>
    /// Ce view model va etre utilisé par els écrans dit de référence. 
    /// C'est à dire les écrans ou seul un (ou deux maximums ) objet(s) métier(s) est(sont) représenté(s) sur celui ci.
    /// Ce sera notamment le cas pour les stades, les équipes, les coupes ainsi que les joeurs.
    /// </summary>
    public class GestionEntitiesViewModel : ViewModelBase
    {
        #region Attributes
        /// <summary>
        /// Model pour les équipes
        /// </summary>
        private ObservableCollection<Equipe> viewTeamModel = new ObservableCollection<Equipe>();
        /// <summary>
        /// Model pour les stades
        /// </summary>
        private ObservableCollection<Stade> viewStadiumModel = new ObservableCollection<Stade>();
        /// <summary>
        /// Model pour les coupes
        /// </summary>
        private ObservableCollection<Coupe> viewCupModel = new ObservableCollection<Coupe>();
        /// <summary>
        /// Model pour les joueurs
        /// </summary>
        private ObservableCollection<Joueur> viewPlayerModel = new ObservableCollection<Joueur>();
        /// <summary>
        /// Model pour les joueurs
        /// </summary>
        private ObservableCollection<Match> viewMatchModel = new ObservableCollection<Match>();
        #endregion

        #region Commandes

        #region Partie Equipe
        public ICommand AddCommandEquipe
        {
            get;
            private set;
        }

        public ICommand UpdateCommandEquipe
        {
            get;
            private set;
        }

        public ICommand EraseCommandEquipe
        {
            get;
            private set;
        }

        public ObservableCollection<Equipe> ViewTeamModel
        {
            get 
            { 
                return viewTeamModel; 
            }
        }
        #endregion

        #region Partie Stades
        public ICommand AddCommandStade
        {
            get;
            private set;
        }

        public ICommand UpdateCommandStade
        {
            get;
            private set;
        }

        public ICommand EraseCommandStade
        {
            get;
            private set;
        }

        public ObservableCollection<Stade> ViewStadiumModel
        {
            get
            {
                return viewStadiumModel;
            }
        }
        #endregion

        #region Partie Coupes
        public ICommand AddCommandCoupe
        {
            get;
            private set;
        }

        public ICommand UpdateCommandCoupe
        {
            get;
            private set;
        }

        public ICommand EraseCommandCoupe
        {
            get;
            private set;
        }

        public ObservableCollection<Coupe> ViewCupModel
        {
            get
            {
                return viewCupModel;
            }
        }
        #endregion

        #region Partie Joueur
        public ICommand AddCommandJoueur
        {
            get;
            private set;
        }

        public ICommand UpdateCommandJoueur
        {
            get;
            private set;
        }

        public ICommand EraseCommandJoueur
        {
            get;
            private set;
        }

        public ObservableCollection<Joueur> ViewPlayerModel
        {
            get
            {
                return viewPlayerModel;
            }
        }
        #endregion

        #region Partie Match
        public ICommand AddCommandMatch
        {
            get;
            private set;
        }

        public ICommand UpdateCommandMatch
        {
            get;
            private set;
        }

        public ICommand EraseCommandMatch
        {
            get;
            private set;
        }

        public ObservableCollection<Match> ViewMatchModel
        {
            get
            {
                return viewMatchModel;
            }
        }
        #endregion

        #endregion

        #region Constructeurs

        public GestionEntitiesViewModel()
        {
            InitListes();

            /** EQUIPE **/
            viewTeamModel.Add(new Equipe());
            AddCommandEquipe = new RelayCommand(AddTeam);
            UpdateCommandEquipe = new RelayCommand(UpdateTeam);
            EraseCommandEquipe = new RelayCommand(EraseTeam);

            /** STADE **/
            viewStadiumModel.Add(new Stade());
            AddCommandStade = new RelayCommand(AddStadium);
            UpdateCommandStade = new RelayCommand(UpdateStadium);
            EraseCommandStade = new RelayCommand(EraseStadium);

            /** COUPE **/
            viewCupModel.Add(new Coupe());
            AddCommandCoupe = new RelayCommand(AddCup);
            UpdateCommandCoupe = new RelayCommand(UpdateCup);
            EraseCommandCoupe = new RelayCommand(EraseCup);

            /** JOUEUR **/
            viewPlayerModel.Add(new Joueur());
            AddCommandJoueur = new RelayCommand(AddPlayer);
            UpdateCommandJoueur = new RelayCommand(UpdatePlayer);
            EraseCommandJoueur = new RelayCommand(ErasePlayer);

            /** MATCH **/
            viewMatchModel.Add(new Match());
            AddCommandMatch = new RelayCommand(AddMatch, AddMatchCanExecute);
            UpdateCommandMatch = new RelayCommand(UpdateMatch, UpdateMatchCanExecute);
            EraseCommandMatch = new RelayCommand(EraseMatch, EraseMatchCanExecute);
        }

        #endregion

        #region Méthodes Command Equipe

        /// <summary>
        /// Ajout d'une équipe
        /// </summary>
        /// <param name="id"> Paramètre non utilisé </param>
        public void AddTeam(object id)
        {
            // Ajouter équipe, prendre le dernier élément de la liste
            // Aucun controle n'a été fait, si l'utilisateur avait sélectionné le premier est fait Add 
            Equipe eqVm = viewTeamModel.Single(r => r.ID == 0);
            eqVm.ID = CoupeManager.Manager.AddTeam(eqVm).ID;
            viewTeamModel.Add(new Equipe());
        }

        /// <summary>
        /// Détermine si l'action Add est possible
        /// </summary>
        /// <param name="parameter"> Paramètre de la Command </param>
        /// <returns> True si action possible </returns>
        public bool AddTeamCanExecute(object parameter)
        {
            return true;
        }

        /// <summary>
        /// Mise à jour d'une équipe
        /// </summary>
        /// <param name="id"> Identifiant de la réservation </param>
        public void UpdateTeam(object id)
        {
            Equipe eq = viewTeamModel.Single(r => r.ID == Convert.ToInt16(id));
            // Mise à jour de l'équipe sélectionnée
            CoupeManager.Manager.UpdateTeam(eq);
        }

        /// <summary>
        /// Détermine si l'action Update est possible
        /// </summary>
        /// <param name="parameter"> Paramètre de la Command </param>
        /// <returns> True si action possible </returns>
        public bool UpdateTeamCanExecute(object parameter)
        {
            return true;
        }

        /// <summary>
        /// Suppression d'une équipe
        /// </summary>
        /// <param name="id"> Identifiant de la réservation </param>
        public void EraseTeam(object id)
        {
            // Supprimer reservation sélectionnée
            //viewReservationModel.Remove(viewReservationModel.Single(r => r.ID == Convert.ToInt16(id)));
            //CoupeManager.Manager.Reservations.Remove(CoupeManager.Manager.Reservations.Single(r => r.ID == Convert.ToInt16(id)));
            viewTeamModel.Remove(viewTeamModel.First(e => e.ID == Convert.ToInt32(id)));
            CoupeManager.Manager.DeleteTeam(Convert.ToInt32(id));
        }

        /// <summary>
        /// Détermine si l'action Erase est possible
        /// </summary>
        /// <param name="parameter"> Paramètre de la Command </param>
        /// <returns> True si action possible </returns>
        public bool EraseTeamCanExecute(object parameter)
        {
            return true;
        }

        #endregion

        #region Méthodes Command Stade
        /// <summary>
        /// Ajout d'un stade
        /// </summary>
        /// <param name="id"> Paramètre non utilisé </param>
        public void AddStadium(object id)
        {
            Stade stVm = viewStadiumModel.Single(r => r.ID == 0);
            stVm.ID = CoupeManager.Manager.AddStadium(stVm).ID;
            viewStadiumModel.Add(new Stade());
        }

        /// <summary>
        /// Détermine si l'action Add est possible
        /// </summary>
        /// <param name="parameter"> Paramètre de la Command </param>
        /// <returns> True si action possible </returns>
        public bool AddStadiumCanExecute(object parameter)
        {
            return true;

        }

        /// <summary>
        /// Mise à jour d'un stade
        /// </summary>
        /// <param name="id"> Identifiant de la réservation </param>
        public void UpdateStadium(object id)
        {
            Stade st = viewStadiumModel.Single(r => r.ID == Convert.ToInt16(id));
            // Mise à jour de l'équipe sélectionnée
            CoupeManager.Manager.UpdateStadium(st);
        }

        /// <summary>
        /// Détermine si l'action Update est possible
        /// </summary>
        /// <param name="parameter"> Paramètre de la Command </param>
        /// <returns> True si action possible </returns>
        public bool UpdateStadiumCanExecute(object parameter)
        {
            return true;

        }

        /// <summary>
        /// Suppression d'un stade
        /// </summary>
        /// <param name="id"> Identifiant de la réservation </param>
        public void EraseStadium(object id)
        {
            viewStadiumModel.Remove(viewStadiumModel.First(e => e.ID == Convert.ToInt32(id)));
            CoupeManager.Manager.DeleteStadium(Convert.ToInt32(id));
        }

        /// <summary>
        /// Détermine si l'action Erase est possible
        /// </summary>
        /// <param name="parameter"> Paramètre de la Command </param>
        /// <returns> True si action possible </returns>
        public bool EraseStadiumCanExecute(object parameter)
        {
            return true;

        }

        #endregion

        #region Méthodes Command Coupe
        /// <summary>
        /// Ajout d'un stade
        /// </summary>
        /// <param name="id"> Paramètre non utilisé </param>
        public void AddCup(object id)
        {
            Coupe cpVm = viewCupModel.Single(r => r.ID == 0);
            cpVm.ID = CoupeManager.Manager.AddCoupe(cpVm).ID;
            viewCupModel.Add(new Coupe());
        }

        /// <summary>
        /// Détermine si l'action Add est possible
        /// </summary>
        /// <param name="parameter"> Paramètre de la Command </param>
        /// <returns> True si action possible </returns>
        public bool AddCupCanExecute(object parameter)
        {
            return true;

        }

        /// <summary>
        /// Mise à jour d'un stade
        /// </summary>
        /// <param name="id"> Identifiant de la réservation </param>
        public void UpdateCup(object id)
        {
            Coupe cp = viewCupModel.Single(r => r.ID == Convert.ToInt16(id));
            // Mise à jour de l'équipe sélectionnée
            CoupeManager.Manager.UpdateCoupe(cp);
        }

        /// <summary>
        /// Détermine si l'action Update est possible
        /// </summary>
        /// <param name="parameter"> Paramètre de la Command </param>
        /// <returns> True si action possible </returns>
        public bool UpdateCupCanExecute(object parameter)
        {
            return true;

        }

        /// <summary>
        /// Suppression d'un stade
        /// </summary>
        /// <param name="id"> Identifiant de la réservation </param>
        public void EraseCup(object id)
        {
            CoupeManager.Manager.DeleteCoupe(Convert.ToInt32(id));
            viewCupModel.Remove(viewCupModel.First(e => e.ID == Convert.ToInt32(id)));
        }

        /// <summary>
        /// Détermine si l'action Erase est possible
        /// </summary>
        /// <param name="parameter"> Paramètre de la Command </param>
        /// <returns> True si action possible </returns>
        public bool EraseCupCanExecute(object parameter)
        {
            return true;

        }

        #endregion

        #region Méthodes Command Joueur
        /// <summary>
        /// Ajout d'un stade
        /// </summary>
        /// <param name="id"> Paramètre non utilisé </param>
        public void AddPlayer(object id)
        {
            Joueur joVm = viewPlayerModel.Single(r => r.ID == 0);
            joVm.ID = CoupeManager.Manager.AddJoueur(joVm).ID;
            viewPlayerModel.Add(new Joueur());
        }

        /// <summary>
        /// Détermine si l'action Add est possible
        /// </summary>
        /// <param name="parameter"> Paramètre de la Command </param>
        /// <returns> True si action possible </returns>
        public bool AddPlayerCanExecute(object parameter)
        {
            return true;

        }

        /// <summary>
        /// Mise à jour d'un stade
        /// </summary>
        /// <param name="id"> Identifiant de la réservation </param>
        public void UpdatePlayer(object id)
        {
            Joueur jo = viewPlayerModel.Single(r => r.ID == Convert.ToInt16(id));
            // Mise à jour de l'équipe sélectionnée
            CoupeManager.Manager.UpdateJoueur(jo);
        }

        /// <summary>
        /// Détermine si l'action Update est possible
        /// </summary>
        /// <param name="parameter"> Paramètre de la Command </param>
        /// <returns> True si action possible </returns>
        public bool UpdatePlayerCanExecute(object parameter)
        {
            return true;

        }

        /// <summary>
        /// Suppression d'un stade
        /// </summary>
        /// <param name="id"> Identifiant de la réservation </param>
        public void ErasePlayer(object id)
        {
            viewPlayerModel.Remove(viewPlayerModel.First(e => e.ID == Convert.ToInt32(id)));
            CoupeManager.Manager.DeleteJoueur(Convert.ToInt32(id));
        }

        /// <summary>
        /// Détermine si l'action Erase est possible
        /// </summary>
        /// <param name="parameter"> Paramètre de la Command </param>
        /// <returns> True si action possible </returns>
        public bool ErasePlayerCanExecute(object parameter)
        {
            return true;

        }

        #endregion

        #region Méthodes Command Match
        /// <summary>
        /// Ajout d'un match
        /// </summary>
        /// <param name="id"> Paramètre non utilisé </param>
        public void AddMatch(object id)
        {
            Match mVm = viewMatchModel.Single(r => r.ID == 0);
            mVm.ID = CoupeManager.Manager.AddMatch(mVm).ID;
            viewMatchModel.Add(new Match());
        }

        /// <summary>
        /// Détermine si l'action Add est possible
        /// </summary>
        /// <param name="parameter"> Paramètre de la Command </param>
        /// <returns> True si action possible </returns>
        public bool AddMatchCanExecute(object parameter)
        {
            return true;

        }

        /// <summary>
        /// Mise à jour d'un match
        /// </summary>
        /// <param name="id"> Identifiant </param>
        public void UpdateMatch(object id)
        {
            Match m = viewMatchModel.Single(r => r.ID == Convert.ToInt16(id));
            // Mise à jour de l'équipe sélectionnée
            CoupeManager.Manager.UpdateMatch(m);
        }

        /// <summary>
        /// Détermine si l'action Update est possible
        /// </summary>
        /// <param name="parameter"> Paramètre de la Command </param>
        /// <returns> True si action possible </returns>
        public bool UpdateMatchCanExecute(object parameter)
        {
            return true;

        }

        /// <summary>
        /// Suppression d'un match
        /// </summary>
        /// <param name="id"> Identifiant </param>
        public void EraseMatch(object id)
        {
            viewMatchModel.Remove(viewMatchModel.First(e => e.ID == Convert.ToInt32(id)));
            CoupeManager.Manager.DeleteMatch(Convert.ToInt32(id));
        }

        /// <summary>
        /// Détermine si l'action Erase est possible
        /// </summary>
        /// <param name="parameter"> Paramètre de la Command </param>
        /// <returns> True si action possible </returns>
        public bool EraseMatchCanExecute(object parameter)
        {
            return true;

        }

        #endregion

        #region Utils

        /// <summary>
        /// Permet d'initialiser les liste d'objets entities
        /// </summary>
        private void InitListes()
        {
            foreach (Equipe equipe in CoupeManager.Manager.Teams)
                viewTeamModel.Add(equipe);

            foreach (Stade stade in CoupeManager.Manager.Stadiums)
                viewStadiumModel.Add(stade);

            foreach (Joueur joueur in CoupeManager.Manager.Joueurs)
                viewPlayerModel.Add(joueur);

            foreach (Coupe coupe in CoupeManager.Manager.Cups)
                viewCupModel.Add(coupe);

            foreach (Match match in CoupeManager.Manager.Matchs)
                viewMatchModel.Add(match);
        }

        #endregion
    }
}
